#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "cmdfifo.h"
#include "at_service.h"
#include "at_base.h"
#include "at_api.h"
#include "object.h"


static int at_api_exec(char *key_name, int argc, char *argv[]);//根据KEY匹配API，并运行相应的APP
static int at_cmdline_split_cb (char *param, int len); //分解AT指令

static int at_cmdline_split (char cmd, char* param);
static int at_cmdline_echo_error (char cmd, char* param);//输出错误信息


//终端系统状态
typedef struct _te_conf
{
    uint8_t     init;           //系统是否初始化 0--未初始化  1--已初始化
    uint8_t     cmd_ch_echo;    //命令行回显  0--不回显 1--回显
    uint16_t    api_total;      //API列表总数
    at_api_list_t *api_list;    //API列表指针
    char *      last_cmdline;   //记录上一条指令
}te_conf_t;


#define     AT_COMMANDLINE_MAX_LEN  512
//at指令缓冲区
static char l_at_cmdline_buffer[AT_COMMANDLINE_MAX_LEN];
//读取at指令字符的回调函数
static int (*l_cb_at_cmdline_char)(char ch);
//TE的状态值
static te_conf_t l_te_conf;

//AT指令命令FIFO处理句柄
static cmd_fifo_cmd_handle_t l_at_action_handle[] = {
    {0, at_cmdline_split}, //拆分命令行，并执行AT指令
    {1, at_cmdline_echo_error}, //输出错误信息
}; //at指令action


//获取at执行指令
static int at_cmdline_cb_get_action_key (char ch);

/******************************************************************************
 * Function:        at_device_init()
 * Description:     初始化at指令终端设备
 * Calls:            
 * Called By:        
 * Input:            
 * Return:           
 * Others:           
 *****************************************************************************/
void at_service_init ()
{
    cmd_fifo_init(l_at_action_handle, sizeof(l_at_action_handle)/sizeof(l_at_action_handle[0])); //初始化cmdfifo

    memset (&l_te_conf, 0, sizeof (l_te_conf));
    l_te_conf.init = 1; //初始化
    l_te_conf.cmd_ch_echo = 1; //命令行回显
    l_te_conf.last_cmdline = NULL; //记录上一条指令
    l_te_conf.api_list = NULL;//API列表指针
    l_te_conf.api_total = 0;  //API列表总数
//    l_te_conf.cb_commandline_get_action_char = at_cmdline_cb_get_action_key;
    l_cb_at_cmdline_char = at_cmdline_cb_get_action_key;

    at_api_init(); //初始化APP列表
}

/******************************************************************************
 * Function:        at_service_destroy()
 * Description:     关闭at指令设备
 * Calls:            
 * Called By:        
 * Input:            
 * Return:           
 * Others:           
 *****************************************************************************/
void at_service_destroy ()
{
    l_te_conf.init = 0; //初始化
    free (l_te_conf.last_cmdline); //记录上一条指令
}


/******************************************************************************
 * Function:        
 * Description:     逐字读取命令行字符，并寻找at指令
 * Calls:            
 * Called By:        
 * Input:           ch --字符
 * Return:          
 * Others:           
 *****************************************************************************/
void at_cmdline_get_char (char ch)
{
    if (l_te_conf.cmd_ch_echo == 1) //命令回显
    {
        at_base_putchar (ch);
    }
    l_cb_at_cmdline_char (ch);
    return;
}



//接收命令行输入，保存AT指令到缓冲区，并执行操作
static int at_cmdline_cb_get_action_key (char ch)
{
    static int flag = 0; //检测AT指令的标识
    static char last_char = '\0'; //上一个字符
    static int index = 0; //l_at_cmdline_buffer的索引位置
    int ret = -1;

    do
    {
        if (ch < 0)  //确保收到的字符是ascii字符
        {
            return -1;
        }
        if (flag == 0) //没检测到at指令
        {
            if ((last_char == 'a' && 
                        (ch == 't' || ch == '/'))
                    || ( last_char == 'A' && 
                        (ch == 'T' || ch == '/')))
            {
                flag = 1; //检测到AT指令
                index = 0;
                if (ch == '/')
                {
                   if (l_te_conf.last_cmdline != NULL)
                   {
                       //at_base_putstring (l_te_conf.last_cmdline);
                       at_cmdline_action (l_te_conf.last_cmdline); //激活命令行
                   }
                    break;
                }
            }
        }
        else  //检测到at指令
        {
            l_at_cmdline_buffer [index] = ch; //保存字符
            if (index >= AT_COMMANDLINE_MAX_LEN) //防止缓冲区溢出
            {
                ret = -1;
                break;
            }
            if (last_char == '\r' && ch == '\n') //AT指令行结束
            {
                l_at_cmdline_buffer [index - 1] = '\0'; //字符串结尾
               // printf ("AT指令%s\t[%d]\n", l_at_cmdline_buffer, strlen (l_at_cmdline_buffer));
                if (index == 1)
                {
                    at_base_putstring ("\r\nOK\r\n");
                    break;
                }

                at_cmdline_action (l_at_cmdline_buffer); //激活命令行
                ret = 0;
                break;
            }
            else if (ch == 0x08) //响应退格键
            {
                l_at_cmdline_buffer  [--index] = 0;
                return 0;
            }
            index ++;
        }
    
        last_char = ch; //记录本次字符
        return 0;
    }
    while (0);

    /*异常处理*/
    last_char = '\0';
    flag = 0;
    index = 0;
    /*l_at_cmdline_buffer [0] = '\0'; //为节省周期，不清除缓冲区*/
    memset (l_at_cmdline_buffer, '\0', AT_COMMANDLINE_MAX_LEN);//清除缓冲区
    return ret;
}


/******************************************************************************
 * Function:        at_cmdline_action()
 * Description:     激活AT指令，把命令行推入执行fifo
 * Calls:            
 * Called By:       at_cmdline_get_char()
 * Input:           cmdline --命令行
 * Return:          0 --执行成功
 *                  -1 --执行失败
 * Others:              
 *****************************************************************************/
int at_cmdline_action (char *cmdline)
{
    int ret = -1;
    char *cmd = NULL;
    /*cmd = (char *) calloc (strlen(cmdline)%10+1, 10); */
    cmd = strdup(cmdline); //为执行命令分配内存， 
                           //把命令行参数推入执行fifo
    if (cmd != NULL)
    {
        cmd_fifo_add (0, cmd); 
    }
    else{ //内存错误
        cmd_fifo_add (1, NULL);
    }
    return ret;
}

  


//拆分命令行，如果有“;”，要拆为多条，被main_loop执行
/******************************************************************************
 * Function:        at_cmdline_split()
 * Description:     拆分命令行，如果有“;”拆为多条,并逐条执行
 * Calls:           at_cmdline_split_cb()
 * Called By:       main_loop()
 * Input:           cmd --cmdfifo的指令标识
 * Return:          0 --执行成功
 * Others:          none
 *****************************************************************************/
static int at_cmdline_split (char cmd, char* param)
{
    int i = 0;
    object_t *tmp = NULL;
    char *par = NULL;
    int len = strlen(param);
    
    l_te_conf.last_cmdline = (char *)realloc(l_te_conf.last_cmdline, 
            ((len+1)/10 + 1)*10);
    strncpy (l_te_conf.last_cmdline, param, len); //保存到上一条指令记录

    tmp = object_string_split (param, ';', QUOTES);
    if (tmp != NULL)
    {
        for (i = 1; i <= object_string_get_field_total(tmp); i ++)
        {
            par = object_string_get_field_string (tmp, i);
            at_cmdline_split_cb (par, strlen(par)); //执行AT指令
        }
    }
    else
    {
        at_cmdline_split_cb (param, len); //执行AT指令
    }
    object_free (tmp);
    
    /*printf ("执行命令: %s\n", param);*/
    return 0;
}

static int at_cmdline_echo_error (char cmd, char* param)
{
    if (param == NULL)
    {
        at_base_putstring ("\r\nERROR\r\n");
    }
    else
    {
    at_base_putstring (param);
    }
    return 0;
}

/******************************************************************************
 * Function:        at_cmdline_echo_en()
 * Description:     命令行回显使能
 * Calls:            
 * Called By:        
 * Input:           en  0-不回显    1--回显
 * Return:          void
 * Others:          none
 *****************************************************************************/
void at_cmdline_echo_en(char en)
{
    if (en == 0)
    {
        l_te_conf.cmd_ch_echo = 0;
    }
    else
    {
        l_te_conf.cmd_ch_echo = 1;
    }
}

//AT指令服务主循环
void at_service_main_loop ()
{
    cmd_fifo_main_loop ();
}


//AT指令API列表注册
void at_api_list_register (at_api_list_t *api_list, int num)
{
    if (api_list != NULL)
    {
        l_te_conf.api_list = api_list;
        l_te_conf.api_total = num;
    }
}

//根据KEY匹配API，并运行相应的APP
static int at_api_exec(char *key_name, int argc, char *argv[])
{
    int i;
    /*fprintf (stdout, "执行命令：%s\t[%02d]\n", key_name, argc);*/
    /*fprintf (stdout, "参数列表：\n");*/
    //fprintf (stdout, "执行命令：%s\t[%02d]\n", key_name, argc);

    for (i = 0; i < l_te_conf.api_total; i ++)
    {
        if (strcmp (key_name, (l_te_conf.api_list + i)->key_name) == 0)
        {
            (l_te_conf.api_list + i)->api_func (argc, argv);
            return 0;
        }
    }
    at_cmdline_echo_error (0, NULL);
    /*at_base_putstring ("\r\nOK\r\n");*/
    return 0;
}

//分解AT指令
static int at_cmdline_split_cb (char *param, int len)
{
    object_t *tmp = NULL;
    object_t *par = NULL; //解析出参数列表
    char *key_name = NULL;
    int key_name_len = 0;
    int argc = 0;
    int i;
    char **argv = NULL;
    tmp = object_string_split(param, '=', QUOTES);
    do
    {
        if (object_string_get_field_total (tmp) >= 2)
        {
            par = object_string_split (object_string_get_field_string(tmp, 2),  //分割参数
                    ',', QUOTES);
            if (par != NULL)
            {
                argc = object_string_get_field_total (par);
                argv = par->field_list; //参数列表
            }
        }

        /*把KEY变成大写*/
        key_name = object_string_get_field_string(tmp, 1);
        key_name_len = strlen (key_name);
        for (i = 0; i < key_name_len; i ++)
        {
            key_name[i]>=97&&key_name[i]<=122?key_name[i]-=32:key_name[i];
        }
        
        at_api_exec (key_name, argc, argv);
        object_free (par); //释放
        object_free (tmp); //释放
    }while(0);
    fflush (stdout);
    return 0;
}

